package com.allwees.support.fileservice;

import com.allwees.bs.core.modelbase.vo.R;
import com.allwees.core.common.util.DateUtil;
import com.allwees.support.fileservice.config.AwsConfig;
import com.allwees.support.fileservice.service.UserUuidAware;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import software.amazon.awssdk.services.sts.StsClient;
import software.amazon.awssdk.services.sts.model.AssumeRoleRequest;
import software.amazon.awssdk.services.sts.model.AssumeRoleResponse;
import software.amazon.awssdk.services.sts.model.Credentials;

import javax.annotation.Resource;
import java.util.Date;

/**
 * 获取aws s3的access token
 * @author Daniel
 * @version 1.0.0
 * @since 2020/11/11 12:29
 */
@RestController
@RequestMapping("/api/upload/token")
@Slf4j
public class AwsTokenController {

    public static final int DEFAULT_DURATION_SECONDS = 3600 * 12;

    @Resource
    private StsClient stsClient;

    @Resource
    private AwsConfig awsConfig;

    @Resource
    private UserUuidAware userUuidAware;

    /**
     * 为当前用户分配session token的session id模板 <br>
     * 格式：session-{module}-{userUuid}
     */
    private static final String SESSION_NAME_PATTERN = "session-%s";
    /**
     * 当前用户上传文件的路径(即前缀) <br>
     * 格式：{module}/{userUuid}/{yyyyMMdd}/{uuid}
     */
    private static final String KEY_PREFIX_PATTERN = "%s/%s/%s/";

    /**
     * session policy模板，会据此和s3中的objectKey控制申请access token用户的权限,<br>
     * 防止用户横向越权，修改、删除不属于其名下的文件资源
     */
    private static final String SESSION_POLICY_PATTERN = "{\n" +
            "    \"Version\": \"2012-10-17\",\n" +
            "    \"Statement\": [\n" +
            "        {\n" +
            "            \"Effect\": \"Allow\",\n" +
            "            \"Action\": [\n" +
            "                \"s3:PutObject\",\n" +
            "                \"s3:PutObjectAcl\"\n" +
            "            ],\n" +
            "            \"Resource\": [\n" +
            "                \"arn:aws:s3:::{0}/cat/{1}/*\",\n" +
            "                \"arn:aws:s3:::{0}/ads/{1}/*\",\n" +
            "                \"arn:aws:s3:::{0}/msg/{1}/*\",\n" +
            "                \"arn:aws:s3:::{0}/aud/{1}/*\",\n" +
            "                \"arn:aws:s3:::{0}/spu/{1}/*\",\n" +
            "                \"arn:aws:s3:::{0}/stt/{1}/*\",\n" +
            "                \"arn:aws:s3:::{0}/avr/{1}/*\",\n" +
            "                \"arn:aws:s3:::{0}/rev/{1}/*\",\n" +
            "                \"arn:aws:s3:::{0}/rfd/{1}/*\",\n" +
            "                \"arn:aws:s3:::{0}/fdk/{1}/*\"\n" +
            "           ]\n" +
            "        }\n" +
            "    ]\n" +
            "}";

    /**
     * 根据当前登录用户和业务模块为其分配一个s3的access token.<br>
     * 该token拥有上传文件至指定路径并设置其acl的权限.
     * @param module 所属的业务模块
     * @return
     */
    @GetMapping("/{module}")
    public R generateToken(@PathVariable("module") String module) {
        Assert.isTrue(isValidImgType(module),"Invalid module~");
        String userUuid = userUuidAware.getCurrentUserUuid();
        String bucketName = awsConfig.getBucket();
        String sessionPolicy = SESSION_POLICY_PATTERN.replace("{0}",bucketName).replace("{1}",userUuid);
        AssumeRoleRequest roleRequest = AssumeRoleRequest.builder()
                .roleArn(awsConfig.getRoleArn())
                .policy(sessionPolicy)
                .roleSessionName(String.format(SESSION_NAME_PATTERN,userUuid))
                .durationSeconds(DEFAULT_DURATION_SECONDS)
                .build();

        AssumeRoleResponse roleResponse = stsClient.assumeRole(roleRequest);
        Credentials credentials = roleResponse.credentials();
        AwsToken awsToken = new AwsToken(
                credentials.accessKeyId(),
                credentials.secretAccessKey(),
                credentials.sessionToken(),
                DEFAULT_DURATION_SECONDS,
                awsConfig.getRegion(),
                bucketName,
                String.format(KEY_PREFIX_PATTERN,module,userUuid,getFormatDay()),
                awsConfig.getBasePath()

        );
        return R.ok(awsToken);
    }

    private boolean isValidImgType(String imgType){
        return awsConfig.getModules().contains(imgType);
    }

    private String getFormatDay(){
        return DateUtil.formatDate(new Date(),"yyyyMMdd");
    }


//    private static void doPutObject(AwsToken awsToken){
//        String objectKey = awsToken.getKeyPrefix() + ".png";
//        String objectPath = "C:\\Users\\Administrator\\Desktop\\b.png";
//
//
//        AwsSessionCredentials credentials = AwsSessionCredentials.create(
//                awsToken.getAccessKeyId(),
//                awsToken.getSecretAccessKey(),
//                awsToken.getSessionToken());
//
//        S3Client s3 = S3Client.builder()
//                .credentialsProvider(StaticCredentialsProvider.create(credentials))
//                .region(Region.of(awsToken.getRegion()))
//                .build();
//
//        try {
//            PutObjectResponse response = s3.putObject(
//                    PutObjectRequest.builder()
//                            .bucket(awsToken.getBucketName())
//                            .key(objectKey)
//                            .acl(ObjectCannedACL.PUBLIC_READ)
//                            .build(),
//                    RequestBody.fromBytes(Files.readAllBytes(Paths.get(objectPath))));
//            System.out.println(response.eTag());
//        } catch (IOException e) {
//            e.printStackTrace();
//        }
//    }
}
